﻿using DataType;
using DataType.Actions;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using DataType.MessageType;
using DataType.ShootJudgeTables;
using MapCalclator;
using OprsSimulator.Operators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace ActionsJudge
{
    internal static class IndirectedShootJudge
    {
        public static List<IJudgeResult> ToJudge(List<OperatorMsg> oprs, Dictionary<JMPointsMsg, List<OperatorMsg>> jmJudgeObjs, IndirectedShootJudgeTable indirectedshootJudgeTab, Map map)
        {
            // 保存裁决结果，用于返回
            List<IJudgeResult> judgeResults = new List<IJudgeResult>();

            // 间瞄射击裁决
            foreach (var jmJudgeObj in jmJudgeObjs)// 遍历 间瞄点 和 会被此间瞄点裁决的算子们 的键值对
            {
                JMPointsMsg jmp = jmJudgeObj.Key;// 间瞄点
                List<OperatorMsg> targetOprs = jmJudgeObj.Value;// 会被此间瞄点裁决的算子们

                int ori_damage;// 初始战损
                bool offset = false;// 是否散射
                AlignType align_status = AlignType.NoAlign;// 校射类型

                // 随机数1、随机数2、第三个随机数、第三个随机数的修正值
                int random1, random2, ori_random2, random2_rect;
                // 生成随机数1
                Random random = new Random();
                int r11 = random.Next(1, 7);
                int r12 = random.Next(1, 7);
                random1 = r11 + r12;
                if (random1 < 2) random1 = 2;
                if (random1 > 12) random1 = 12;

                // 检查校射
                OperatorMsg jm_opr;// 发射此间瞄点的炮兵算子
                int index = -1;// 炮兵的索引
                // 寻找炮兵算子
                for (int j = 0; j < oprs.Count; j++)
                {
                    if (oprs[j].obj_id == jmp.obj_id)
                    {
                        index = j;
                    }
                }
                if (index != -1)// 找到发射间瞄火力的算子
                {
                    jm_opr = oprs[index];// 用索引赋值
                    bool align_flag = false;// 是否有校射的标志位
                    bool target_align_flag = false;// 目标校射 的标志位
                    List<int> targetOprIDs = new List<int>();// 记录裁决目标的id

                    // 检查是否存在目标，记录目标id，用于校射判断
                    for (int j = 0; j < targetOprs.Count; j++)
                    {
                        if (targetOprs[j].cur_hex == jmp.pos)
                        {
                            targetOprIDs.Add(targetOprs[j].obj_id);
                        }
                    }
                    // 格内存在算子，检查是否可以目标校射
                    if (targetOprIDs.Count > 0)
                    {
                        for (int j = 0; j < oprs.Count; j++)
                        {
                            // 排除不能进行校射的算子
                            if (oprs[j].color != jm_opr.color)// 敌方算子不可以
                            {
                                continue;
                            }
                            if (oprs[j].type != (int)OprType.Vehicle && oprs[j].type != (int)OprType.Infantry && oprs[j].sub_type != (int)OprSubType.Drone)// 除了我方地面单位和无人机之外的算子不可以
                            {
                                continue;
                            }
                            // 用目标id检查是否可以目标校射
                            foreach (int id in targetOprIDs)
                            {
                                // 如果目标算子可以被看见
                                if (oprs[j].see_enemy_bop_ids.Contains(id))
                                {
                                    // 可以目标校射
                                    target_align_flag = true;
                                    align_flag = true;// 校射完成
                                    align_status = AlignType.TargetAlign;// 校射类型为目标校射
                                    break;
                                }
                            }
                            // 是目标校射
                            if (target_align_flag)// 放foreach循环外，以跳出for循环（此处目标校射与间瞄点更新时的校射判断保持一致，即能看到格中某一个就裁决为目标校射）
                            {
                                int judgeTabValue = indirectedshootJudgeTab.GetTargetAlignJMFireDispersal(random1);// 用随机数1调表查看火力是散布还是命中
                                if (judgeTabValue >= 0)// 裁决表的值大于等于0为散布
                                {
                                    offset = true;
                                }
                                else if (judgeTabValue == -1)// 裁决表的值小于0为命中
                                {
                                    offset = false;// 没有散布
                                }
                                break;
                            }
                        }
                    }

                    int distance = map.GetDistance(jm_opr.cur_hex, jmp.pos);// 取得炮兵算子和间瞄点之间的距离，用于查裁决表
                    // 如果不是目标校射，或者格内无算子，或者算子不可视
                    if (!target_align_flag || targetOprIDs.Count == 0)
                    {
                        // 检测格内校射
                        for (int j = 0; j < oprs.Count; j++)
                        {
                            // 排除不能进行校射的算子
                            if (oprs[j].color != jm_opr.color)// 敌方算子不可以
                            {
                                continue;
                            }
                            if (oprs[j].type != (int)OprType.Vehicle && oprs[j].type != (int)OprType.Infantry && oprs[j].sub_type != (int)OprSubType.Drone)// 除了我方地面单位和无人机之外的算子不可以
                            {
                                continue;
                            }
                            // 可以看见目标格，即可以格内校射
                            if (map.CanSee(oprs[j].cur_hex, jmp.pos))
                            {
                                int judgeTabValue = indirectedshootJudgeTab.GetHexAlignJMFireDispersal(distance, random1);// 用distance和random1调表查看火力是散布还是命中
                                if (judgeTabValue >= 0)// 裁决表的值大于等于0为散布
                                {
                                    offset = true;
                                }
                                else if (judgeTabValue == -1)// 裁决表的值小于0为命中
                                {
                                    offset = false;// 没有散布
                                }

                                align_flag = true;// 校射完成
                                align_status = AlignType.HexAlign;// 校射类型为格内校射

                                break;
                            }
                        }
                    }
                    // 没有校射，即无校射
                    if (!align_flag)
                    {
                        int judgeTabValue = indirectedshootJudgeTab.GetNoAlignJMFireDispersal(distance, random1);// 用distance和random1调表查看火力是散布还是命中
                        if (judgeTabValue >= 0)// 裁决表的值大于等于0为散布
                        {
                            offset = true;
                        }
                        else if (judgeTabValue == -1)// 裁决表的值小于0为命中
                        {
                            offset = false;// 没有散布
                        }
                        align_status = AlignType.NoAlign;// 校射类型为无校射
                    }

                    // 生成随机数2
                    int r1 = random.Next(1, 7);
                    int r2 = random.Next(1, 7);
                    random2 = r1 + r2;
                    if (random2 < 2) random2 = 2;
                    if (random2 > 12) random2 = 12;
                    // 散射裁决
                    if (offset)
                    {
                        ori_damage = indirectedshootJudgeTab.GetDeviateTargetDamage((WeaponType)jmp.weapon_id, random2);// 用武器id和随机数2查火力偏离目标战斗结果表，取得初始战损
                    }
                    // 命中裁决
                    else
                    {
                        ori_damage = indirectedshootJudgeTab.GetHitTargetDamage((WeaponType)jmp.weapon_id, random2);// 用武器id和随机数2查火力命中目标战斗结果表，取得初始战损
                    }
                    // damage为-1表示无伤害，但是压制
                    bool keep_flag = false;// 裁决为压制的标志位
                    if (ori_damage == -1)// 如果初始战损为-1表示没有伤害的纯压制
                    {
                        ori_damage = 0;// 战损置零
                        keep_flag = true;// 压制标志位为true
                    }

                    // 战斗结果修正
                    int val = 0;// 记录修正值
                    if (map[jmp.pos / 100, jmp.pos % 100].cond == TerrainType.City) val -= 1;// 攻击目标在城镇
                    if (map[jmp.pos / 100, jmp.pos % 100].cond == TerrainType.Forest) val -= 2;// 攻击目标在丛林
                    switch (jm_opr.blood)// 进行间瞄的炮兵的血量（班数，即火炮数量）
                    {
                        case 1: val -= 4; break;// 血量为1
                        case 2: val -= 2; break;// 血量为2
                        case 3: val -= 0; break;// 血量为3
                        case 4: val += 2; break;// 血量为4
                    }
                    // 对每个具体目标的具体修正
                    foreach (OperatorMsg targetOpr in targetOprs)
                    {
                        int num = 0;// 记录目标状态而产生的修正值
                        if (targetOpr.move_state == (int)MoveStateType.Shelt) num -= 2;// 目标掩蔽
                        if (targetOpr.type == (int)OprType.Infantry && targetOpr.speed > 0) num += 2;// 目标是人员算子且正在机动
                        if (targetOpr.stack) num += 2;// 目标堆叠
                        if (targetOpr.move_state == (int)MoveStateType.March) num += 4;// 目标行军
                        if (targetOpr.armor == (int)ArmorType.CompositeArmor) num -= 3;// 目标为复合装甲
                        if (targetOpr.armor == (int)ArmorType.HeavyArmor) num -= 1;// 目标为重型装甲
                        if (targetOpr.armor == (int)ArmorType.MediamArmor) num -= 0;// 目标为中型装甲
                        if (targetOpr.armor == (int)ArmorType.LightArmor) num += 1;// 目标为轻型装甲

                        // 生成第三个随机数
                        int r21 = random.Next(1, 7);
                        int r22 = random.Next(1, 7);
                        ori_random2 = r21 + r22;
                        random2_rect = ori_random2 + val + num;// 用两个修正值对第三个随机数修正

                        // 计算最终战损damage
                        int damage_rect = 0;// 战损修正值
                        if (random2_rect <= 1) damage_rect = -2;// 随机数小于等于1，修正值为-2
                        else if (random2_rect >= 2 && random2_rect <= 4) damage_rect = -1;// 随机数在2-4之间，修正值为-1
                        else if (random2_rect >= 5 && random2_rect <= 7) damage_rect = 0;// 随机数在5-7之间，修正值为0
                        else if (random2_rect >= 8) damage_rect = 1;// 随机数大于等于8，修正值为1

                        int damage = ori_damage + damage_rect;// 初始战损加上修正值为最终战损
                        // 无伤害无压制 --> 无效打击
                        if (damage == 0)
                        {
                            if (!keep_flag)
                            {
                                damage = -1;
                            }
                        }

                        bool flag_indirected_shoot;// 有效射击的标志位
                        if (damage < 0)// 最终战损小于0为无效
                        {
                            flag_indirected_shoot = false;
                        }
                        else
                        {
                            flag_indirected_shoot = true;// 最终战损大于等于0为有效
                        }

                        // 生成裁决结果，添加进judgeResults
                        IndirectedShootJudgeResult indirectedShootJudgeResult = new IndirectedShootJudgeResult(
                            jmp.obj_id, flag_indirected_shoot, align_status, offset, jm_opr.obj_id, jm_opr.blood, (Color)jm_opr.color, (OprSubType)jm_opr.sub_type, damage, distance, ori_damage, random1, random2, ori_random2, random2_rect, damage_rect,
                            (Color)targetOpr.color, targetOpr.obj_id, (OprSubType)targetOpr.sub_type, (WeaponType)jmp.weapon_id);
                        judgeResults.Add(indirectedShootJudgeResult);
                    }
                }
                else
                {
                    //炮兵被打掉
                }
            }

            return judgeResults;
        }
    }
}
